﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ZCustomControl.Helpers;
using ZCustomControl.Models;

namespace ZCustomControl.Controls
{
    public class WindowController : Control
    {
        #region Fields

        private Button _btnMin = null;
        private Button _btnNormal = null;
        private Button _btnMax = null;
        private Button _btnClose = null;

        private Func<bool> _closeConfirm = null;

        #endregion

        #region Properties 

        public Func<bool> CloseConfirm
        {
            get => _closeConfirm;
            set => _closeConfirm = value;
        }

        #endregion

        #region Dependency Properties

        /// <summary>
        /// 窗口控制模式（使用默认方法或者自定义）
        /// </summary>
        public static readonly DependencyProperty WindowControlModeProperty
            = DependencyProperty.Register("WindowControlMode", typeof(WindowControlMode), typeof(WindowController), new PropertyMetadata(WindowControlMode.Default));
        /// <summary>
        /// 当前窗口控制类型
        /// </summary>
        public static readonly DependencyProperty WindowControlTypeProperty
            = DependencyProperty.Register("WindowControlType", typeof(WindowControlType), typeof(WindowController), new PropertyMetadata(WindowControlType.None, OnWindowControlTypeChanged));
        /// <summary>
        /// 指示控件是否显示最小化按钮
        /// </summary>
        public static readonly DependencyProperty IsShowMinButtonProperty
            = DependencyProperty.Register("IsShowMinButton", typeof(bool), typeof(WindowController), new PropertyMetadata(true, OnIsShowMinButtonPropertyChanged));
        /// <summary>
        /// 指示控件是否显示最大化按钮（最大化按钮和还原按钮同时显示隐藏）
        /// </summary>
        public static readonly DependencyProperty IsShowMaxButtonProperty
            = DependencyProperty.Register("IsShowMaxButton", typeof(bool), typeof(WindowController), new PropertyMetadata(true, OnIsShowMaxButtonPropertyChanged));
        /// <summary>
        /// 指示是否显示关闭按钮
        /// </summary>
        public static readonly DependencyProperty IsShowCloseButtonProperty
            = DependencyProperty.Register("IsShowCloseButton", typeof(bool), typeof(WindowController), new PropertyMetadata(true, OnIsShowCloseButtonPropertyChanged));

        #endregion

        #region Dependency Property Wrappers

        public WindowControlMode WindowControlMode
        {
            get { return (WindowControlMode)GetValue(WindowControlModeProperty); }
            set { SetValue(WindowControlModeProperty, value); }
        }

        public WindowControlType WindowControlType
        {
            get { return (WindowControlType)GetValue(WindowControlTypeProperty); }
            set { SetValue(WindowControlTypeProperty, value); }
        }

        public bool IsShowMinButton
        {
            get { return (bool)GetValue(IsShowMinButtonProperty); }
            set { SetValue(IsShowMinButtonProperty, value); }
        }

        public bool IsShowMaxButton
        {
            get { return (bool)GetValue(IsShowMaxButtonProperty); }
            set { SetValue(IsShowMaxButtonProperty, value); }
        }

        public bool IsShowCloseButton
        {
            get { return (bool)GetValue(IsShowCloseButtonProperty); }
            set { SetValue(IsShowCloseButtonProperty, value); }
        }

        #endregion

        #region Routed Events

        public static readonly RoutedEvent ChangeWindowStateEvent
            = EventManager.RegisterRoutedEvent("ChangeWindowState", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(WindowController));

        #endregion

        #region Routed Event Wrappers

        public event RoutedEventHandler ChangeWindowState
        {
            add
            {
                base.AddHandler(ChangeWindowStateEvent, value);
            }
            remove
            {
                base.RemoveHandler(ChangeWindowStateEvent, value);
            }
        }

        #endregion

        #region Constructors

        static WindowController()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(WindowController), new FrameworkPropertyMetadata(typeof(WindowController)));
        }

        #endregion

        #region Override Methods

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _btnMin = GetTemplateChild("PART_ButtonMin") as Button;
            if (_btnMin != null)
            {
                _btnMin.Tag = WindowControlType.Minimized;
                _btnMin.Click += WindowControl_Click;
            }

            _btnMax = GetTemplateChild("PART_ButtonMax") as Button;
            if (_btnMax != null)
            {
                _btnMax.Tag = WindowControlType.Maximized;
                _btnMax.Click += WindowControl_Click;
            }

            _btnNormal = GetTemplateChild("PART_ButtonNormal") as Button;
            if (_btnNormal != null)
            {
                _btnNormal.Tag = WindowControlType.Normal;
                _btnNormal.Click += WindowControl_Click;
            }

            _btnClose = GetTemplateChild("PART_ButtonClose") as Button;
            if (_btnClose != null)
            {
                _btnClose.Tag = WindowControlType.Close;
                _btnClose.Click += WindowControl_Click;
            }

            Window win = LVTreeHelper.GetAncestor<Window>(this);
            if (win != null)
            {
                UpdateButtonVisibility((WindowControlType)((int)win.WindowState));
            }
        }

        #endregion

        #region Property Changed Callback

        /// <summary>
        /// 窗口控制枚举改变回调方法--设置控件按钮的显示隐藏
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void OnWindowControlTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WindowController winCtrl = d as WindowController;
            if (winCtrl == null)
            {
                return;
            }

            winCtrl.UpdateButtonVisibility((WindowControlType)e.NewValue);
        }

        private static void OnIsShowCloseButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WindowController winCtrl = d as WindowController;
            if (winCtrl == null)
            {
                return;
            }
            winCtrl.UpdateButtonVisibility(winCtrl.WindowControlType);
        }

        private static void OnIsShowMaxButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WindowController winCtrl = d as WindowController;
            if (winCtrl == null)
            {
                return;
            }
            winCtrl.UpdateButtonVisibility(winCtrl.WindowControlType);
        }

        private static void OnIsShowMinButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WindowController winCtrl = d as WindowController;
            if (winCtrl == null)
            {
                return;
            }
            winCtrl.UpdateButtonVisibility(winCtrl.WindowControlType);
        }

        #endregion

        #region Event Methods

        /// <summary>
        /// 多按钮统一点击事件处理方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WindowControl_Click(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;
            if (button == null)
            {
                return;
            }

            //获取按钮所代表的控制状态
            WindowControlType = (WindowControlType)button.Tag;

            //窗口关闭时执行确认关闭方法
            if (WindowControlType == WindowControlType.Close && _closeConfirm != null && !_closeConfirm())
            {
                return;
            }

            WindowControl();
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// 根据窗口控制状态设置控制按钮的显示隐藏
        /// </summary>
        /// <param name="winControlType"></param>
        private void UpdateButtonVisibility(WindowControlType winControlType)
        {
            if (_btnClose != null)
            {
                if (IsShowCloseButton)
                {
                    _btnClose.Visibility = Visibility.Visible;
                }
                else
                {
                    _btnClose.Visibility = Visibility.Collapsed;
                }
            }

            if (_btnMin != null)
            {
                if (IsShowMinButton)
                {
                    _btnMin.Visibility = Visibility.Visible;
                }
                else
                {
                    _btnMin.Visibility = Visibility.Collapsed;
                }
            }

            if (_btnMax != null && _btnNormal != null)//这两个控件必须同时存在
            {
                if (IsShowMaxButton)//只有允许按钮显示是才会根据窗口状态控制按钮的显示隐藏
                {
                    if (winControlType == WindowControlType.Normal)
                    {
                        _btnNormal.Visibility = Visibility.Collapsed;
                        _btnMax.Visibility = Visibility.Visible;
                    }
                    else if (winControlType == WindowControlType.Maximized)
                    {
                        _btnNormal.Visibility = Visibility.Visible;
                        _btnMax.Visibility = Visibility.Collapsed;
                    }
                }
                else
                {
                    _btnNormal.Visibility = Visibility.Collapsed;
                    _btnMax.Visibility = Visibility.Collapsed;
                }
            }
        }

        /// <summary>
        /// 控件默认的窗口控制方法
        /// </summary>
        /// <param name="winControlType"></param>
        private void DefaulWindowControl(WindowControlType winControlType)
        {
            Window win = LVTreeHelper.GetAncestor<Window>(this);
            if (win == null)
            {
                return;
            }

            if (winControlType == WindowControlType.Close)
            {
                win.Close();
            }
            else if (winControlType != WindowControlType.None)
            {
                WindowState winState = (WindowState)((int)winControlType);
                win.WindowState = winState;
                UpdateButtonVisibility(winControlType);
            }
        }

        /// <summary>
        /// 控制窗口，根据WindowControlMode属性选择特定的控制方法
        /// </summary>
        private void WindowControl()
        {
            if (WindowControlMode == WindowControlMode.Default)
            {
                DefaulWindowControl(WindowControlType);
            }
            else
            {
                RoutedEventArgs args = new RoutedEventArgs(ChangeWindowStateEvent, this);
                RaiseEvent(args);
            }
        }

        #endregion
    }
}
